package com.yichi.detector;

import android.graphics.PointF;
import android.graphics.Rect;
import android.util.Log;

import com.google.mlkit.vision.face.Face;
import com.google.mlkit.vision.face.FaceLandmark;

import java.util.Arrays;
import java.util.Locale;

public class HeadPoseDetector {
    private static final String TAG = "LiveDetector";

    // 状态枚举
    private enum DetectionState {
        CALIBRATING,    // 校准阶段（等待回正）
        LEFT_TURN,      // 左转检测
        RIGHT_TURN,     // 右转检测
        COMPLETED       // 完成检测
    }

    public enum Action {
        LEFT,
        RIGHT
    }

    // 配置参数
    private static final int CALIBRATION_STABLE_FRAMES = 5; // 降低为5帧
    private static final float SPEED_THRESHOLD = 20f;     // 放宽速度限制
    private static final float SMOOTHNESS_VARIANCE = 8f;  // 放宽平滑度
    private static final long CALIBRATION_TIMEOUT = 5000; // 5秒校准超时
    // 修改参数配置
    private static final float LEFT_ANGLE_THRESHOLD = -15f;  // 左转阈值
    private static final float RIGHT_ANGLE_THRESHOLD = 15f;  // 右转阈值
    private static final float CENTER_THRESHOLD = 5f;        // 正对阈值
    private static final float MAX_ACCELERATION = 30f; // 最大允许加速度（度/秒²）
    private float previousSpeed = 0f;
    // 状态变量
    private DetectionState currentState = DetectionState.CALIBRATING;
    // 移除initialYaw相关变量
    private float currentYaw;
    private long calibrationStartTime = 0;

    // 运动检测
    private float lastYaw = 0f;
    private long lastYawTime = 0;
    private final float[] movementSpeeds = new float[5];
    private int speedIndex = 0;
    // 新增初始角度记录
    private float initialYaw = 0f;

    public boolean validateHeadMovement(Face face, Action action) {
        long currentTime = System.currentTimeMillis();
//        // 处理校准超时
//        if (currentState == DetectionState.CALIBRATING &&
//                currentTime - calibrationStartTime > CALIBRATION_TIMEOUT) {
//            reset();
//            return false;
//        }


        switch (currentState) {
            case CALIBRATING:
                handleCalibration(face, action);
                break;
            case LEFT_TURN:
            case RIGHT_TURN:
                if (checkTurnValid(face, action, currentTime)) {
                    currentState = DetectionState.COMPLETED;
                    return true;
                }
                break;

            case COMPLETED:
                reset();
                return true;
        }


        return false;
    }

    private void handleCalibration(Face face, Action action) {
        if (calibrationStartTime == 0) {
            calibrationStartTime = System.currentTimeMillis();
        }
        if (isFaceCentered(face)) {
            initialYaw = face.getHeadEulerAngleY(); // 保存初始角度
            currentState = action == Action.LEFT ?
                    DetectionState.LEFT_TURN :
                    DetectionState.RIGHT_TURN;
            Log.i(TAG, "校准成功，初始角度：" + initialYaw + "°");
            resetCalibration();
        } else {
            calibrationStartTime = 0;
            Log.d(TAG, "头部偏移 重置校准");
        }
    }

    // 修改角度计算方法
    private float calculateRotationAngle() {
        return currentYaw - initialYaw; // 实际旋转角度
    }


    // 修改重置方法
    private void resetCalibration() {
        calibrationStartTime = 0;
    }

    private boolean checkTurnValid(Face face, Action action, long currentTime) {
        currentYaw = face.getHeadEulerAngleY();

        if (!checkNaturalMovement(face)) {
            return false;
        }

        float speed = calculateMovementSpeed(currentYaw, currentTime);

        Log.d(TAG, String.format("当前Yaw: %.1f° 速度: %.1f°/s", currentYaw, speed));

        boolean isCheckAngle = checkAngle(action);
        boolean isCheckSpeed = speed < SPEED_THRESHOLD;
        boolean isCheckMovementSmoothness = checkMovementSmoothness();
        Log.d(TAG, String.format("isCheckAngle: %b, isCheckSpeed: %b, isCheckMovementSmoothness: %b",
                isCheckAngle, isCheckSpeed, isCheckMovementSmoothness));

        return isCheckAngle && isCheckSpeed && isCheckMovementSmoothness;
    }

    // 校验角度是否符合要求
    private boolean checkAngle(Action action) {
        float rotationAngle = calculateRotationAngle();
        Log.d(TAG, "实际旋转角度：" + rotationAngle + "°");

        return action == Action.LEFT ?
                rotationAngle < LEFT_ANGLE_THRESHOLD :
                rotationAngle > RIGHT_ANGLE_THRESHOLD;
    }

    // 计算运动速度（度/秒）
    private float calculateMovementSpeed(float currentYaw, long currentTime) {
        if (lastYawTime == 0) {
            lastYaw = currentYaw;
            lastYawTime = currentTime;
            return 0f;
        }

        // 计算原始速度
        float deltaTime = (currentTime - lastYawTime) / 1000f;
        float deltaYaw = currentYaw - lastYaw;
        float rawSpeed = Math.abs(deltaYaw) / deltaTime;

        // 加速度限制
        float acceleration = Math.abs(rawSpeed - previousSpeed) / deltaTime;
        if (acceleration > MAX_ACCELERATION) {
            Log.w(TAG, "异常加速度过滤: " + acceleration + "°/s²");
            rawSpeed = previousSpeed; // 使用上一帧速度
        }

        // 滑动窗口平均
        movementSpeeds[speedIndex] = rawSpeed;
        speedIndex = (speedIndex + 1) % movementSpeeds.length;

        // 计算平均速度
        float sum = 0;
        int validCount = 0;
        for (float speed : movementSpeeds) {
            if (speed > 0) {
                sum += speed;
                validCount++;
            }
        }
        float avgSpeed = validCount > 0 ? sum / validCount : 0;

        // 更新状态
        previousSpeed = avgSpeed;
        lastYaw = currentYaw;
        lastYawTime = currentTime;

        Log.d(TAG, String.format(Locale.US,
                "速度计算: 原始=%.1f 加速度=%.1f 平均=%.1f",
                rawSpeed, acceleration, avgSpeed
        ));

        return avgSpeed;
    }

    // 检查自然运动（三维协同）
    // 调整自然运动检测
    private boolean checkNaturalMovement(Face face) {
        float pitch = Math.abs(face.getHeadEulerAngleX());
        float roll = Math.abs(face.getHeadEulerAngleZ());

        return pitch < 15f &&
                roll < 10f &&
                Math.abs(currentYaw) > 5f; // 确保有效转动
    }

    // 检查运动平滑度
    private boolean checkMovementSmoothness() {
        float sum = 0, squareSum = 0;
        for (float speed : movementSpeeds) {
            sum += speed;
            squareSum += speed * speed;
        }
        float variance = (squareSum - sum * sum / movementSpeeds.length) / movementSpeeds.length;
        return variance < SMOOTHNESS_VARIANCE;
    }

    // 判断是否回正
    private boolean isFaceCentered(Face face) {
        float yaw = Math.abs(face.getHeadEulerAngleY());
        float pitch = Math.abs(face.getHeadEulerAngleX());
        float roll = Math.abs(face.getHeadEulerAngleZ());

        return yaw < CENTER_THRESHOLD &&
                pitch < CENTER_THRESHOLD &&
                roll < CENTER_THRESHOLD;
    }

    // 修改reset方法
    public void reset() {
        Log.d(TAG, "重置检测器状态");
        currentState = DetectionState.CALIBRATING;
        calibrationStartTime = System.currentTimeMillis();
        lastYaw = 0f;
        lastYawTime = 0;
        previousSpeed = 0f;
        Arrays.fill(movementSpeeds, 0f);
        speedIndex = 0;
        initialYaw = 0f;
    }

}
